<?php

namespace Common\Service;

use Common\Service\MerWxSettingService;

class WechatSdk {

  private $app_id;
  private $app_secret;
  private $wx_setting;
  var $error = '';

  public function __construct($app_id, $app_secret) {
    $this->app_id = $app_id;
    $this->app_secret = $app_secret;
    $this->wx_setting = MerWxSettingService::instance();
    $this->error = '';
  }

  public function get_sign_package() {
    $jsapiTicket = $this->get_js_api_ticket();

    // 注意 URL 一定要动态获取，不能 hardcode.
    $protocol = (!empty($_SERVER ['HTTPS']) && $_SERVER ['HTTPS'] !== 'off' || $_SERVER ['SERVER_PORT'] == 443) ? "https://" : "http://";
    $url = "$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";

    $timestamp = time();
    $nonceStr = $this->create_nonce_str();

    // 这里参数的顺序要按照 key 值 ASCII 码升序排序
    $string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";

    $signature = sha1($string);

    $signPackage = array(
      "appId" => $this->app_id,
      "nonceStr" => $nonceStr,
      "timestamp" => $timestamp,
      "url" => $url,
      "signature" => $signature,
      "rawString" => $string
    );
    return $signPackage;
  }

  private function create_nonce_str($length = 16) {
    $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    $str = "";
    for ($i = 0; $i < $length; $i ++) {
      $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
    }
    return $str;
  }

  public function _get_js_api_ticket() {
    $wx_setting = M('WX');

    // jsapi_ticket 应该全局存储与更新，以下代码以写入到文件中做示例
    $data = json_decode(file_get_contents("./Public/tmp/jsapi_ticket.json"));

    if ($data->expire_time < time()) {
      $accessToken = $this->_get_access_token();
      // 如果是企业号用以下 URL 获取 ticket
      // $url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=$accessToken";
      $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=$accessToken";

      $res = json_decode($this->_http_get($url));

      $ticket = $res->ticket;

      if ($ticket) {
        $data->expire_time = time() + 7000;
        $data->jsapi_ticket = $ticket;
        $fp = fopen("./Public/tmp/jsapi_ticket.json", "w");
        fwrite($fp, json_encode($data));
        fclose($fp);
      }
    } else {
      $ticket = $data->jsapi_ticket;
    }

    return $ticket;
  }

  private function _get_access_token() {
    // 读取access token 是否过期
    $wx_data = $this->wx_setting->get_by_appid_appsecret($this->app_id, $this->app_secret);
    // 取本地 access_token;
    if (!empty($wx_data ['access_token'])) {
      $access_token = json_decode($wx_data ['access_token'], TRUE);
      if ($access_token ['access_token_expire'] > time()) {
        // 如果未超时
        return $access_token ['access_token'];
      }
    }

    // 重新获取
    $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" . $this->app_id . "&secret=" . $this->app_secret;
    $res = json_decode($this->_http_get($url), TRUE);
    if (isset($res ['errcode'])) {
      $this->error = 'access_token 获取失败(' . $res ['errmsg'] . ')';
      return FALSE;
    }
    $save_data = array(
      'access_token_expire' => time() + 7000,
      'access_token' => $res ['access_token']
    );

    // 保存到数据库
    $this->wx_setting->save_access_token_by_appid_appsecret($this->app_id, $this->app_secret, $save_data);
    return $res ['access_token'];
  }

  private function _http_get($url) {
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_TIMEOUT, 500);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($curl, CURLOPT_URL, $url);
    // 优化
    curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
      'Expect: '
    ));
    curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
    $res = curl_exec($curl);
    curl_close($curl);

    return $res;
  }

  private function _http_post($url, $data) {
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_TIMEOUT, 500);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_POST, 1);
    curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
    // 优化
    curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
      'Expect: '
    ));
    curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
    $res = curl_exec($curl);
    curl_close($curl);

    return $res;
  }

  /**
   * 取自定义菜单
   *
   * @return type
   */
  function get_menu() {
    $access_token = $this->_get_access_token();
    if (!$access_token) {
      return ajax_arr($this->error);
    }

    $url = 'https://api.weixin.qq.com/cgi-bin/menu/get?access_token=' . $access_token;
    $ret = json_decode($this->_http_get($url), TRUE);

    if ($ret ['errcode'] != 0) {
      return ajax_arr($ret ['errmsg'], FALSE);
    } else {
      return ajax_arr('读取菜单成功', TRUE, $ret);
    }
  }

  /**
   * 发布菜单
   *
   * @param type $data          
   * @return type
   */
  function post_menu($data) {
    $access_token = $this->_get_access_token();
    if (!$access_token) {
      return ajax_arr($this->error);
    }
    $url = 'https://api.weixin.qq.com/cgi-bin/menu/create?access_token=' . $access_token;

    $str = json_encode($data, JSON_UNESCAPED_UNICODE);
    $ret = json_decode($this->_http_post($url, $str), TRUE);

    if ($ret ['errcode'] != 0) {
      return ajax_arr($ret ['errmsg'], FALSE, $ret);
    } else {
      return ajax_arr('发布菜单成功', TRUE, $ret);
    }
  }

  /**
   * 发送消息接口，
   * 如果 openid 为数组 则调用群发接口，每用户每月4次
   * 如果 openid 不是数组 则调用客服接口，互动用户48小时内可发送
   * 当用户主动发消息给公众号的时候（包括发送信息、点击自定义菜单、订阅事件、
   * 扫描二维码事件、支付成功事件、用户维权），
   * 微信将会把消息数据推送给开发者，开发者在一段时间内（目前修改为48小时）
   *
   * @param type $openid          
   * @param type $content          
   * @return type
   */
  function sendText($openid, $content) {
    $access_token = $this->_get_access_token();

    // 多用户群发（服务号）
    $url = 'https://api.weixin.qq.com/cgi-bin/message/mass/send?access_token=' . $access_token;

    $post = array(
      'touser' => $openid,
      'msgtype' => 'text',
      'text' => array(
        'content' => $content
      )
    );

    $str = json_encode($post, JSON_UNESCAPED_UNICODE);
    $ret = json_decode($this->_http_post($url, $str), TRUE);

    if ($ret ['errcode'] != 0) {
      return ajax_arr($ret ['errmsg'], FALSE);
    } else {
      return ajax_arr('推送文本消息成功', TRUE, $ret);
    }
  }

  function get_pushmediaid_from_material($media_id) {
    $old_media = $this->get_material_by_mediaid($media_id);
    if (!isset($old_media ['news_item'])) {
      return ajax_arr('图文信息未取到');
    }

    // 生成要推送的新图文信息
    // 要重新生成图片的 media_id
    $articles = array();
    foreach ($old_media ['news_item'] as $row) {
      $row ['thumb_media_id'] = $this->get_newsimg_mediaid($row ['thumb_media_id']);
      $articles [] = $row;
    }

    // 上传要推送的news的media_id
    $push_media_data = $this->upload_pushmsg_media($articles);

    if (!isset($push_media_data ['media_id'])) {
      return ajax_arr('上传推送图文失败');
    }

    return ajax_arr('OK', TRUE, array(
      'media_id' => $push_media_data ['media_id']
      ));
  }

  /**
   * 客服接口发消息
   *
   * @param type $openid          
   * @param type $content          
   * @return type
   */
  function sendMsg($openid, $content) {
    $access_token = $this->_get_access_token();
    $url = 'https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=' . $access_token;

    $post = array(
      'touser' => $openid,
      'msgtype' => 'text',
      'text' => array(
        'content' => $content
      )
    );

    $str = json_encode($post, JSON_UNESCAPED_UNICODE);
    $ret = json_decode($this->_http_post($url, $str), TRUE);

    if ($ret ['errcode'] != 0) {
      return ajax_arr($ret ['errmsg'], FALSE);
    } else {
      return ajax_arr('发送消息成功', TRUE, $ret);
    }
  }

  function sendNews($openid, $meida_id) {
    if (!is_array($openid)) {
      return ajax_arr($openid . ' 不正确', FALSE);
    }
    $access_token = $this->_get_access_token();

    // 多用户群发（服务号）
    $url = 'https://api.weixin.qq.com/cgi-bin/message/mass/send?access_token=' . $access_token;

    $post = array(
      'touser' => $openid,
      'msgtype' => 'mpnews',
      'mpnews' => array(
        'media_id' => $meida_id
      )
    );

    $str = json_encode($post, JSON_UNESCAPED_UNICODE);
    $ret = json_decode($this->_http_post($url, $str), TRUE);

    if ($ret ['errcode'] != 0) {
      return ajax_arr($ret ['errmsg'], FALSE);
    } else {
      return ajax_arr('推送图文消息成功', TRUE, $ret);
    }
  }

  /**
   * 按组发送消息
   *
   * @param type $content          
   * @param type $group_id          
   * @return type
   */
  function sendmsg_by_group($content, $group_id = 0) {
    $access_token = $this->_get_access_token();
    $url = 'https://api.weixin.qq.com/cgi-bin/message/mass/sendall?access_token=' . $access_token;

    $post = array(
      'filter' => array(
        'is_to_all' => $group_id > 0 ? FALSE : TRUE,
        'group_id' => $group_id
      ),
      'msgtype' => 'text',
      'text' => array(
        'content' => $content
      )
    );

    $str = json_encode($post, JSON_UNESCAPED_UNICODE);
    $ret = json_decode($this->_http_post($url, $str), TRUE);

    if ($ret ['errcode'] != 0) {
      return ajax_arr($ret ['errmsg'], FALSE);
    } else {
      return ajax_arr('发送消息成功', TRUE, $ret);
    }
  }

  /**
   * 创建用户分组
   *
   * @param type $group_name          
   * @return type
   */
  function create_group($group_name) {
    $access_token = $this->_get_access_token();
    $url = 'https://api.weixin.qq.com/cgi-bin/groups/create?access_token=' . $access_token;

    $post = array(
      'group' => array(
        'name' => $group_name
      )
    );

    $str = json_encode($post, JSON_UNESCAPED_UNICODE);
    $ret = json_decode($this->_http_post($url, $str), TRUE);

    if ($ret ['errcode'] != 0) {
      return ajax_arr($ret ['errmsg'], FALSE);
    } else {
      return ajax_arr('创建用户分组成功', TRUE, $ret);
    }
  }

  function update_group($id, $group_name) {
    $access_token = $this->_get_access_token();
    $url = 'https://api.weixin.qq.com/cgi-bin/groups/create?access_token=' . $access_token;

    $post = array(
      'group' => array(
        'id' => $id,
        'name' => $group_name
      )
    );

    $str = json_encode($post, JSON_UNESCAPED_UNICODE);
    $ret = json_decode($this->_http_post($url, $str), TRUE);

    if ($ret ['errcode'] != 0) {
      return ajax_arr($ret ['errmsg'], FALSE);
    } else {
      return ajax_arr('修改用户分组成功', TRUE, $ret);
    }
  }

  /**
   * 移动用户分组
   * $openid 为数组时批量移动
   *
   * @param type $openid          
   * @param type $group_id          
   * @return type
   */
  function move_user_to_group($openid, $group_id) {
    $access_token = $this->_get_access_token();
    if (!is_array($openid)) {
      $url = 'https://api.weixin.qq.com/cgi-bin/groups/members/update?access_token=' . $access_token;
      $post = array(
        'openid' => $openid,
        'to_groupid' => $group_id
      );
    } else {
      $url = 'https://api.weixin.qq.com/cgi-bin/groups/members/batchupdate?access_token=' . $access_token;
      $post = array(
        'openid_list' => $openid,
        'to_groupid' => $group_id
      );
    }

    $str = json_encode($post, JSON_UNESCAPED_UNICODE);
    $ret = json_decode($this->_http_post($url, $str), TRUE);

    if ($ret ['errcode'] != 0) {
      return ajax_arr($ret ['errmsg'], FALSE);
    } else {
      return ajax_arr('移动用户分组成功', TRUE, $ret);
    }
  }

  /**
   * 获取用户增减数据
   *
   * @param type $begin_date          
   * @param type $end_date          
   * @return type
   */
  function getUserCumulate($begin_date = '', $end_date = '') {
    $access_token = $this->_get_access_token();
    $url = 'https://api.weixin.qq.com/datacube/getusercumulate?access_token=' . $access_token;

    if (empty($begin_date) || empty($end_date)) {
      $begin_date = $end_date = date('Y-m-d', strtotime('-1 day'));
    }

    $data = array(
      'begin_date' => $begin_date,
      'end_date' => $end_date
    );

    $str = json_encode($data);
    $ret = json_decode($this->_http_post($url, $str), TRUE);

    return $ret;
  }

  /**
   * 获取累计用户数据
   *
   * @param type $return_type          
   * @param type $begin_date          
   * @param type $end_date          
   * @return type
   */
  function getUserSummary($return_type = 'list', $begin_date = '', $end_date = '') {
    $access_token = $this->_get_access_token();
    $url = 'https://api.weixin.qq.com/datacube/getusersummary?access_token=' . $access_token;

    if (empty($begin_date) || empty($end_date)) {
      $begin_date = $end_date = date('Y-m-d', strtotime('-1 day'));
    }

    $data = array(
      'begin_date' => $begin_date,
      'end_date' => $end_date
    );

    $str = json_encode($data);
    $ret = json_decode($this->_http_post($url, $str), TRUE);
    // print_r($ret);
    if ($return_type == 'list') {
      return $ret;
    } elseif ($return_type == 'total') {
      return $this->getTotalUserSummary($ret);
    }
  }

  function getTotalUserSummary($data) {
    $arr = array(
      'new' => 0,
      'cancel' => 0
    );
    foreach ($data ['list'] as $row) {
      $arr ['new'] += $row ['new_user'];
      $arr ['cancel'] += $row ['cancel_user'];
    }
    return $arr;
  }

  function get_media_count() {
    $access_token = $this->_get_access_token();
    $url = 'https://api.weixin.qq.com/cgi-bin/material/get_materialcount?access_token=' . $access_token;
    $ret = json_decode($this->_http_get($url), TRUE);

    // print_r( $ret );
    return $ret;
  }

  function get_media($type = 'news', $offset = 0, $count = 20) {
    $access_token = $this->_get_access_token();
    $url = 'https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token=' . $access_token;

    $data = array(
      "type" => $type,
      "offset" => $offset,
      "count" => $count
    );

    $str = json_encode($data);
    $ret = json_decode($this->_http_post($url, $str), TRUE);

    return $ret;
  }

  // https://api.weixin.qq.com/cgi-bin/material/get_material?access_token=ACCESS_TOKEN
  function get_img($media_id = '') {
    if (empty($media_id)) {
      return '';
    }

    $this_day_path = './Public/upload/wx/' . date('ymd');
    if (!file_exists($this_day_path)) {
      mkdir($this_day_path, 0777);
    }

    $filename = $this_day_path . '/' . $media_id . '.jpg';

    $access_token = $this->_get_access_token();
    $url = 'https://api.weixin.qq.com/cgi-bin/material/get_material?access_token=' . $access_token;

    $data = array(
      'media_id' => $media_id
    );
    $str = json_encode($data);

    $img_data = $this->_http_post($url, $str);
    file_put_contents($filename, $img_data);
    return $filename;
  }

  /**
   * 上传 素材库图片
   *
   * @param type $filename          
   * @return type
   */
  function upload_img($filename) {
    $access_token = $this->_get_access_token();
    $url = "http://api.weixin.qq.com/cgi-bin/material/add_material?access_token=$access_token&type=image";

    $data = array(
      'media' => '@' . realpath($filename)
    );

    $ret = json_decode($this->_http_post($url, $data), TRUE);
    return $ret;
  }

  /**
   * 上传 推送图片
   *
   * @param type $filename          
   * @return type
   */
  function upload_media($filename) {
    $access_token = $this->_get_access_token();
    $url = "http://file.api.weixin.qq.com/cgi-bin/media/upload?access_token=$access_token&type=image";

    $data = array(
      'media' => '@' . realpath($filename)
    );

    $ret = json_decode($this->_http_post($url, $data), TRUE);
    return $ret;
  }

  function get_newsimg_mediaid($media_id) {
    $media_data = $this->get_img_by_mediaid($media_id);
    $filepath = './Public/upload/tmp/' . md5(time() . rand(1000, 9999)) . '.jpg';
    file_put_contents($filepath, $media_data);
    $upload_ret = $this->upload_media($filepath);

    unlink($filepath);
    return $upload_ret ['media_id'];
  }

  function get_material_by_mediaid($media_id) {
    $access_token = $this->_get_access_token();
    $url = "https://api.weixin.qq.com/cgi-bin/material/get_material?access_token=" . $access_token;

    $data = array(
      "media_id" => $media_id
    );

    $str = json_encode($data);
    $ret = json_decode($this->_http_post($url, $str), TRUE);

    return $ret;
  }

  function get_img_by_mediaid($media_id) {
    $access_token = $this->_get_access_token();
    $url = "https://api.weixin.qq.com/cgi-bin/material/get_material?access_token=" . $access_token;

    $data = array(
      "media_id" => $media_id
    );

    $str = json_encode($data);
    return $this->_http_post($url, $str);
  }

  /**
   *
   * @param type $media_data          
   * @return type {
   *         "type":"news",
   *         "media_id":"CsEf3ldqkAYJAU6EJeIkStVDSvffUJ54vqbThMgplD-VJXXof6ctX5fI6-aYyUiQ",
   *         "created_at":1391857799
   *         }
   */
  function upload_pushmsg_media($media_data) {
    $access_token = $this->_get_access_token();
    $url = "https://api.weixin.qq.com/cgi-bin/media/uploadnews?access_token=" . $access_token;

    $data = array(
      "articles" => $media_data
    );

    $str = json_encode($data, JSON_UNESCAPED_UNICODE);
    $ret = json_decode($this->_http_post($url, $str), TRUE);

    return $ret;
  }

  function get_page_access_token_by_code($code) {
    $appid = $this->app_id;
    $appsecret = $this->app_secret;
    $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=$appid&secret=$appsecret&code=$code&grant_type=authorization_code";

    $ret = $this->_http_get($url);

    return json_decode($ret, TRUE);
  }

  /**
   * 微信模板消息
   *
   * @param unknown $template_id          
   * @param unknown $data          
   */
  function send_template_message($touser, $template_id, $url, $data, $topcolor = "#FF0000") {
    $access_token = $this->_get_access_token();
    $wx = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=$access_token";
    $post = array(
      "touser" => $touser,
      "template_id" => $template_id,
      "url" => $url,
      "topcolor" => $topcolor,
      "data" => $data
    );
    $str = json_encode($post, JSON_UNESCAPED_UNICODE);
    $ret = json_decode($this->_http_post($wx, $str), TRUE);
    return $ret;
  }
  
  function create_qrcode( $user_id ) {
    $access_token = $this->_get_access_token();
    if (!$access_token) {
      return ajax_arr($this->error);
    }

    $url = 'https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=' . $access_token;
    $post = array(
      "action_name" => 'QR_LIMIT_STR_SCENE',
      "action_info" => array(
        'scene' => array(
          'scene_str' => (string)$user_id ,
        ),
      )
    );
    $str = json_encode($post, JSON_UNESCAPED_UNICODE);
    $ret = json_decode($this->_http_post($url, $str), TRUE);
    if ( isset( $ret['errcode'] ) && $ret['errcode'] > 0 ) {
      $this->error = $ret['errmsg'];
      return ;
    }
    $img_url = 'https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=' . urlencode($ret['ticket']);
    //echo $img_url ;
    $filepath = './Public/upload/wechat/' . date('Ym');
    if ( !file_exists($filepath) ) {
      mkdir($filepath, 0777);
    }
    $filename = $filepath .'/' . rand_string(18) . '.jpg';
    $img = file_get_contents($img_url); 
    file_put_contents( $filename , $img );
    
    return $filename ;
  }

}
